/*FreeMind - A Program for creating and viewing Mindmaps
*Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others.
*
*See COPYING for Details
*
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
/*
 * Created on 11.12.2005
 * Copyright (C) 2005 Dimitri Polivaev
 */
package freemind.modes.mindmapmode.attributeactors;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Iterator;
import java.util.Map;

import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreeSelectionModel;

import freemind.controller.Controller;
import freemind.controller.MapModuleManager;
import freemind.controller.filter.util.SortedComboBoxModel;
import freemind.main.Resources;
import freemind.main.Tools;
import freemind.modes.MindIcon;
import freemind.modes.MindMap;
import freemind.modes.attributes.AttributeRegistry;
import freemind.modes.attributes.AttributeRegistryElement;
import freemind.view.MapModule;

class ImportAttributesDialog extends JDialog implements TreeSelectionListener {
    private JTree tree;
    private JScrollPane scrollPane;
    private DefaultMutableTreeNode topNode;
    private AttributeRegistry currentAttributes;
    static private class TreeNodeInfo{
        private String info;
        static private final int FULL_SELECTED = 0;
        static private final int PARTIAL_SELECTED = 1;
        static private final int NOT_SELECTED = 2;

        private int selected;

        public TreeNodeInfo(String info) {
            this.info = info;
            this.selected = NOT_SELECTED;
        }

        int getSelected() {
            return selected;
        }

        void setSelected(int selected) {
            this.selected = selected;
        }

        String getInfo() {
            return info;
        }

         public String toString(){
            return info;
        }
    }
    static private class AttributeTreeNodeInfo extends TreeNodeInfo{
        private boolean restricted;

        public AttributeTreeNodeInfo(String info, boolean restricted) {
            super(info);
            this.restricted = restricted;
        }
        boolean isRestricted() {
            return restricted;
        }

    }
    static private class MyRenderer extends DefaultTreeCellRenderer {
        static final Icon iconFull = MindIcon.factory("button_ok").getIcon();
        static final Icon iconPartial = MindIcon.factory("forward").getIcon();
        static final Icon iconNotSelected = MindIcon.factory("button_cancel").getIcon();
        public MyRenderer() {
        }

        public Component getTreeCellRendererComponent(
                JTree tree,
                Object value,
                boolean sel,
                boolean expanded,
                boolean leaf,
                int row,
                boolean hasFocus) {

            super.getTreeCellRendererComponent(
                    tree, value, false,
                    expanded, leaf, row,
                    false);

            DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
            TreeNodeInfo info = (TreeNodeInfo) node.getUserObject() ;
            switch(info.getSelected()){
            case TreeNodeInfo.FULL_SELECTED:
                setIcon(iconFull);
                break;
            case TreeNodeInfo.PARTIAL_SELECTED:
                setIcon(iconPartial);
                break;
            case TreeNodeInfo.NOT_SELECTED:
                setIcon(iconNotSelected);
                break;
            }
            return this;
        }
    }

    MyRenderer renderer = null;
    private DefaultTreeModel treeModel;
    private Component parentComponent;
    private Controller c;
    public ImportAttributesDialog(final Controller c, final Component parentComponent){
        super(c.getJFrame(), Resources.getInstance().getResourceString("attributes_import"), true);
        this.c = c;
        this.parentComponent = parentComponent;
        TreeNodeInfo nodeInfo = new TreeNodeInfo(Resources.getInstance().getResourceString("attribute_top"));
        topNode = new DefaultMutableTreeNode(nodeInfo);
        treeModel = new DefaultTreeModel(topNode);
        tree = new JTree(treeModel);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.addTreeSelectionListener(this);

        scrollPane = new JScrollPane();
        scrollPane.setViewportView(tree);
        scrollPane.setPreferredSize(new Dimension(600, 300));
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        Box buttons = Box.createHorizontalBox();
        buttons.setBorder(new EmptyBorder(5, 5, 5, 5));

        JButton okBtn = new JButton();
        Tools.setLabelAndMnemonic(okBtn, Resources.getInstance().getResourceString("ok"));
        okBtn.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {
                performImport(topNode);
                dispose();
            }

        });

        JButton cancelBtn = new JButton();
        Tools.setLabelAndMnemonic(cancelBtn, Resources.getInstance().getResourceString("cancel"));
        cancelBtn.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {
            	dispose();
            }

        });
        buttons.add(Box.createHorizontalGlue());
        buttons.add(okBtn);
        buttons.add(Box.createHorizontalGlue());
        buttons.add(cancelBtn);
        buttons.add(Box.createHorizontalGlue());

        getContentPane().add(buttons, BorderLayout.SOUTH);
        
        Tools.addEscapeActionToDialog(this);
     }
    
	public void show() {
		createMapSubTrees(topNode);
		if(topNode.getChildCount() == 0){
			JOptionPane.showMessageDialog(parentComponent,
					Resources.getInstance().getResourceString("atributes_no_import_candidates_found"),
					getTitle(),
					JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		treeModel.reload();
		if(renderer == null){
			renderer = new MyRenderer();
		}
		tree.setCellRenderer(renderer);
		setLocationRelativeTo(parentComponent);
		pack();
		super.show();
	}

    private void performImport(DefaultMutableTreeNode node) {
        TreeNodeInfo info = (TreeNodeInfo) node.getUserObject();
        if(info.getSelected() == TreeNodeInfo.NOT_SELECTED){
            return;
        }
        String name = info.getInfo();
        boolean attributeNameRegistered = false;
        for(int i = 0; i < node.getChildCount(); i++){
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i);
            if(childNode.isLeaf()){
                if(attributeNameRegistered == false){
                    attributeNameRegistered = true;
                    if(-1 == currentAttributes.indexOf(name)){
                       currentAttributes.getAttributeController().performRegistryAttribute(name);
                       int index = currentAttributes.indexOf(name);
                       currentAttributes.getAttributeController().performSetRestriction(index, ((AttributeTreeNodeInfo)info).isRestricted());
                    }
                }
                TreeNodeInfo childInfo = (TreeNodeInfo) childNode.getUserObject();
                if(childInfo.getSelected() == TreeNodeInfo.FULL_SELECTED){
                    String value = childInfo.getInfo();
                    currentAttributes.getAttributeController().performRegistryAttributeValue(name, value);
                }
            }
            else{
                performImport(childNode);
            }
        }

    }

    private void createMapSubTrees(DefaultMutableTreeNode top) {
        top.removeAllChildren();
        TreeNodeInfo topInfo = (TreeNodeInfo) top.getUserObject();
        topInfo.setSelected(TreeNodeInfo.NOT_SELECTED);
        MapModuleManager mapModuleManager = c.getMapModuleManager();
        MindMap currentMap = mapModuleManager.getMapModule().getModel();
        currentAttributes = currentMap.getRegistry().getAttributes();
        Iterator iterator = mapModuleManager.getMapModules().entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry entry = (Map.Entry)iterator.next();
            String nextmapName = entry.getKey().toString();
            MapModule nextMapModule = (MapModule) entry.getValue();
            MindMap nextMap = nextMapModule.getModel();
            if(nextMap == currentMap){
                continue;
            }
            TreeNodeInfo treeNodeInfo = new TreeNodeInfo(nextmapName);
            DefaultMutableTreeNode mapInfo = new DefaultMutableTreeNode(treeNodeInfo);
            createAttributeSubTrees(mapInfo, nextMap.getRegistry().getAttributes());
            if(mapInfo.getChildCount() != 0){
                top.add(mapInfo);
            }
        }


    }
    private void createAttributeSubTrees(DefaultMutableTreeNode mapInfo, AttributeRegistry attributes) {
        for(int i = 0; i < attributes.size();i++){
            AttributeRegistryElement element = attributes.getElement(i);
            TreeNodeInfo treeNodeInfo = new AttributeTreeNodeInfo(element.getKey().toString(), element.isRestricted());
            DefaultMutableTreeNode attributeInfo = new DefaultMutableTreeNode(treeNodeInfo);
            createValueSubTrees(attributeInfo, element, currentAttributes);
            if(attributeInfo.getChildCount() != 0){
                mapInfo.add(attributeInfo);
            }
        }
    }
    private void createValueSubTrees(DefaultMutableTreeNode attributeInfo, AttributeRegistryElement element, AttributeRegistry currentAttributes) {
        String attributeName = element.getKey().toString();
        SortedComboBoxModel values = element.getValues();
        for(int i = 0; i < values.getSize(); i++){
            Object nextElement = values.getElementAt(i);
            if(! currentAttributes.exist(attributeName, nextElement)){
                TreeNodeInfo treeNodeInfo = new TreeNodeInfo(nextElement.toString());
                DefaultMutableTreeNode valueInfo = new DefaultMutableTreeNode(treeNodeInfo);
                attributeInfo.add(valueInfo);
            }
        }
    }

    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
        if(selectedNode == null){
            return;
        }
        TreeNodeInfo info = (TreeNodeInfo) selectedNode.getUserObject();
        int newSelectionType;
        switch(info.getSelected()){
        case TreeNodeInfo.FULL_SELECTED:
            newSelectionType = TreeNodeInfo.NOT_SELECTED;
            break;
        default:
            newSelectionType = TreeNodeInfo.FULL_SELECTED;
            break;
        }
        setSelectionType(selectedNode, newSelectionType);
        setParentSelectionType(selectedNode, newSelectionType);
        tree.clearSelection() ;
    }

    private void setParentSelectionType(DefaultMutableTreeNode selectedNode, int newSelectionType) {
        TreeNode parentNode = selectedNode.getParent();
        if(parentNode == null){
            return;
        }
        DefaultMutableTreeNode defaultMutableParentNode = (DefaultMutableTreeNode)parentNode;
        TreeNodeInfo info = (TreeNodeInfo) (defaultMutableParentNode).getUserObject();
        if(newSelectionType == TreeNodeInfo.PARTIAL_SELECTED){
            if(info.getSelected() != TreeNodeInfo.PARTIAL_SELECTED){
                info.setSelected(TreeNodeInfo.PARTIAL_SELECTED);
                treeModel.nodeChanged(defaultMutableParentNode);
            }
            setParentSelectionType(defaultMutableParentNode, TreeNodeInfo.PARTIAL_SELECTED);
            return;
        }
       for(int i = 0; i < defaultMutableParentNode.getChildCount(); i++){
           TreeNodeInfo childInfo = (TreeNodeInfo) ((DefaultMutableTreeNode)defaultMutableParentNode.getChildAt(i)).getUserObject();
           if(childInfo.getSelected() != newSelectionType){
               if(info.getSelected() != TreeNodeInfo.PARTIAL_SELECTED){
                   info.setSelected(TreeNodeInfo.PARTIAL_SELECTED);
                   treeModel.nodeChanged(defaultMutableParentNode);
               }
               setParentSelectionType(defaultMutableParentNode, TreeNodeInfo.PARTIAL_SELECTED);
               return;
           }
       }
       if(info.getSelected() != newSelectionType){
           info.setSelected(newSelectionType);
           treeModel.nodeChanged(defaultMutableParentNode);
       }
       setParentSelectionType(defaultMutableParentNode, newSelectionType);
    }

    private void setSelectionType(TreeNode selectedNode, int newSelectionType) {
        TreeNodeInfo info = (TreeNodeInfo) ((DefaultMutableTreeNode)selectedNode).getUserObject();
        if(info.getSelected() != newSelectionType){
            info.setSelected(newSelectionType);
            treeModel.nodeChanged(selectedNode);
        }
        for(int i = 0; i < selectedNode.getChildCount(); i++){
            setSelectionType(selectedNode.getChildAt(i), newSelectionType);
        }

    }
}
